home *** CD-ROM | disk | FTP | other *** search
- Subject: v07i051: 2.11 News Source, Part01/09
- Newsgroups: mod.sources
- Approved: mirror!rs
-
- Submitted by: seismo!rick (Rick Adams)
- Mod.sources: Volume 7, Issue 51
- Archive-name: 2.11news/Part11
-
- [ Again, notice the different between the Part# in the Subject line
- and the Part# in the Archive-name. --r$ ]
-
- # To extract, sh this file
- #
- # news 2.11 source part 1 of 9
- #
- if test ! -d src
- then
- mkdir src
- fi
- echo x - src/visual.c 1>&2
- sed 's/.//' >src/visual.c <<'*-*-END-of-src/visual.c-*-*'
- -/*
- - * visual - visual news interface.
- - * Kenneth Almquist
- - */
- -
- -#ifdef SCCSID
- -static char *SccsId = "@(#)visual.c 1.32 10/23/86";
- -#endif /* SCCSID */
- -
- -#include "rparams.h"
- -#ifdef USG
- -#include <sys/ioctl.h>
- -#include <termio.h>
- -#include <fcntl.h>
- -#else /* !USG */
- -#include <sgtty.h>
- -#endif /* !USG */
- -
- -#include <errno.h>
- -#if defined(BSD4_2) || defined(BSD4_1C)
- -#include <sys/dir.h>
- -#else
- -#include "ndir.h"
- -#endif
- -#ifdef BSD4_2
- -#ifndef sigmask
- -#define sigmask(m) (1<<((m)-1))
- -#endif /* !sigmask */
- -#endif /* BSD4_2 */
- -#ifdef MYDB
- -#include "db.h"
- -#endif /* MYDB */
- -
- -extern int errno;
- -
- -#ifdef SIGTSTP
- -#include <setjmp.h>
- -#endif /* SIGTSTP */
- -
- -#define ARTWLEN (ROWS-2)/* number of lines used to display article */
- -#define even(cols) ((cols&1) ? cols + 1 : cols)
- -#ifdef STATTOP
- -#define PRLINE 0 /* prompter line */
- -#define SPLINE 1 /* secondary prompt line */
- -#define ARTWIN 2 /* first line of article window */
- -#define SECPRLEN 81 /* length of secondary prompter */
- -#else
- -#define PRLINE (ROWS-1)/* prompter line */
- -#define SPLINE (ROWS-2)/* secondary prompt line */
- -#define ARTWIN 0 /* first line of article window */
- -#define SECPRLEN 100 /* length of secondary prompter */
- -#endif
- -
- -#define PIPECHAR '|' /* indicate save command should pipe to program */
- -#define META 0200 /* meta character bit (as in emacs) */
- -/* print (display) flags */
- -#define HDRONLY 0001 /* print header only */
- -#define NOPRT 0002 /* don't print at all */
- -#define NEWART 0004 /* force article display to be regenerated */
- -#define HELPMSG 0010 /* display currently contains help message */
- -/* prun flags */
- -#define CWAIT 0001 /* type "continue?" and wait for return */
- -#define BKGRND 0002 /* run process in the background */
- -/* values of curflag */
- -#define CURP1 1 /* cursor after prompt */
- -#define CURP2 2 /* cursor after secondary prompt */
- -#define CURHOME 3 /* cursor at home position */
- -/* flags for vsave routine */
- -#define SVHEAD 01 /* write out article header */
- -#define OVWRITE 02 /* overwrite the file if it already exists */
- -/* other files */
- -
- -#define saveart oobit = bit;strcpy(ofilename1, filename);strcpy(ogroupdir, groupdir);hptr = h;h = hold;hold = hptr;ongsize = pngsize
- -#define NLINES(h, fp) (h->numlines[0] ? h->intnumlines : (h->intnumlines=linecnt(fp),sprintf(h->numlines, "%d", h->intnumlines), h->intnumlines))
- -
- -/* terminal handler stuff */
- -extern int _junked;
- -#define clearok(xxx, flag) _junked = flag
- -extern int COLS;
- -extern int ROWS;
- -extern int hasscroll;
- -
- -FILE *tmpfile();
- -char *getmailname();
- -#ifdef MYDB
- -char *findparent();
- -#endif /* MYDB */
- -int onint();
- -int onstop();
- -int xxit();
- -
- -char *Progname = "vnews"; /* for xerror */
- -
- -/* variables shared between vnews routines */
- -static char linebuf[LBUFLEN]; /* temporary workspace */
- -static FILE *tfp; /* temporary file */
- -static char tfname[] = "/tmp/vnXXXXXX"; /* name of temp file */
- -static long artbody; /* offset of body into article */
- -static int quitflg; /* if set, then quit */
- -static int erased; /* current article has been erased */
- -static int artlines; /* # lines in article body */
- -static int artread; /* entire article has been read */
- -static int hdrstart; /* beginning of header */
- -static int hdrend; /* end of header */
- -static int lastlin; /* number of lines in tempfile */
- -static int tflinno = 0; /* next line in tempfile */
- -static int maxlinno; /* number of lines in file + folded */
- -static char secpr[SECPRLEN]; /* secondary prompt */
- -static char prompt[30]; /* prompter */
- -static short prflags; /* print flags (controls updscr) */
- -static short curflag; /* where to locate cursor */
- -static int dlinno; /* top line on screen */
- -static char timestr[20]; /* current time */
- -static int ismail; /* true if user has mail */
- -static char *mailf; /* user's mail file */
- -static int alflag; /* set if unprocessed alarm signal */
- -static int atend; /* set if at end of article */
- -static char cerase; /* erase character */
- -static char ckill; /* kill character */
- -static char cintr; /* interrupt character */
- -#ifdef TIOCGLTC
- -static char cwerase; /* word erase character */
- -#endif /* TIOCGLTC */
- -short ospeed; /* terminal speed NOT STATIC */
- -static int intflag; /* set if interrupt received */
- -
- -#ifdef SIGTSTP
- -static int reading; /* to keep stupid BSD from restarting reads */
- -jmp_buf intjmp, alrmjmp;
- -#endif /* SIGTSTP */
- -
- -#ifdef MYDB
- -static int hasdb; /* true if article data base exists */
- -#endif /* MYDB */
- -
- -#ifdef DIGPAGE
- -static int endsuba; /* end of sub-article in digest */
- -#endif
- -
- -#ifdef MYDEBUG
- -FILE *debugf; /* file to write debugging info on */
- -#endif
- -
- -char *tft = "/tmp/folXXXXXX";
- -
- -/*
- - * These were made static for u370 with its buggy cc.
- - * I judged it better to have one copy with no ifdefs than
- - * to conditionally compile them as automatic variables
- - * in readr (which they originally were). Performance
- - * considerations might warrant moving some of the simple
- - * things into register variables, but I don't know what
- - * breaks the u370 cc.
- - */
- -static char goodone[BUFLEN]; /* last decent article */
- -static char ogroupdir[BUFLEN]; /* last groupdir */
- -static char edcmdbuf[128];
- -static int rfq = 0; /* for last article */
- -static long ongsize; /* Previous ngsize */
- -static long pngsize; /* Printing ngsize */
- -static char *bptr; /* temp pointer. */
- -static char *tfilename; /* temporary file name */
- -static char ofilename1[BUFLEN]; /* previous file name */
- -static struct hbuf hbuf1, hbuf2; /* for minusing */
- -static struct hbuf *h = &hbuf1, /* current header */
- - *hold = &hbuf2, /* previous header */
- - *hptr; /* temporary */
- -static char *ptr1, *ptr2, *ptr3; /* for reply manipulation */
- -static int aabs = FALSE; /* TRUE if we asked absolutely */
- -static char *ed, tf[100];
- -static long oobit; /* last bit, really */
- -static int dgest = 0;
- -static FILE *fp; /* current article to be printed*/
- -
- -readr()
- -{
- -
- -#ifdef MYDEBUG
- - debugf = fopen("DEBUG", "w");
- - setbuf(debugf, (char *)NULL);
- -#endif
- - if (aflag) {
- - if (*datebuf) {
- - if ((atime = cgtdate(datebuf)) == -1)
- - xerror("Cannot parse date string");
- - } else
- - atime = 0;
- - }
- -
- - if (SigTrap)
- - xxit(1);
- - (void) mktemp(tfname);
- - (void) close(creat(tfname,0666));
- - if ((tfp = fopen(tfname, "w+")) == NULL)
- - xerror("Can't create temp file");
- - (void) unlink(tfname);
- - mailf = getmailname();
- -#ifdef MYDB
- - if (opendb() >= 0) {
- - hasdb = 1;
- - fputs("Using article data base\n", stderr); /*DEBUG*/
- - getng();
- - }
- -#endif
- - ttysave();
- - (void) signal(SIGINT, onint);
- - (void) signal(SIGQUIT, xxit);
- - if (SigTrap)
- - xxit(1);
- - ttyraw();
- - timer();
- -
- - /* loop reading articles. */
- - fp = NULL;
- - obit = -1;
- - nextng();
- - quitflg = 0;
- - while (quitflg == 0) {
- - if (getnextart(FALSE))
- - break;
- - (void) strcpy(goodone, filename);
- - if (SigTrap)
- - return;
- - vcmd();
- - }
- -
- - if (!news) {
- - fprintf(stderr, "No news.\n");
- - }
- -}
- -
- -/*
- - * Read and execute a command.
- - */
- -vcmd() {
- - register c;
- - char *p;
- - long count;
- - int countset;
- -
- - if (prflags & HDRONLY)
- - appfile(fp, lastlin + 1);
- - else
- - appfile(fp, dlinno + ARTWLEN + 1);
- -
- -#ifdef DIGPAGE
- - endsuba = findend(dlinno);
- - if (artlines > dlinno + ARTWLEN
- - || endsuba > 0 && endsuba < artlines
- -#else
- - if (artlines > dlinno + ARTWLEN
- -#endif
- - || (prflags & HDRONLY) && artlines > hdrend) {
- - atend = 0;
- - if (prflags&HDRONLY || maxlinno == 0)
- - (void) strcpy(prompt, "more? ");
- - else
- -#ifdef DIGPAGE
- - (void) sprintf(prompt, "more(%d%%)? ",
- - ((((endsuba > 0) ?
- - endsuba : (dlinno + ARTWLEN)) -
- - hdrend) * 100) / maxlinno);
- -#else /* !DIGPAGE */
- - (void) sprintf(prompt, "more(%d%%)? ",
- - ((dlinno + ARTWLEN - hdrend) * 100) / maxlinno);
- -#endif /* !DIGPAGE */
- - } else {
- - atend = 1;
- - (void) strcpy(prompt, "next? ");
- - if (!erased)
- - clear(bit); /* article read */
- - }
- - curflag = CURP1;
- - p = prompt + strlen(prompt);
- - countset = 0;
- - count = 0;
- - /*
- - * Loop while accumulating a count, until an action character
- - * is entered. Also handle "meta" here.
- - *
- - * Count is the current count. Countset=0 means no count
- - * currently exists. Countset=1, count=0 is valid and means
- - * a count of 0 has been entered
- - */
- - for (;;) {
- - c = vgetc();
- - if (c == cerase || c == '\b' || c == '\177') {
- - if (countset == 0)
- - break; /* Use as action char */
- - if (count < 10)
- - countset = 0; /* Erase only char of count */
- - else
- - count /= 10L; /* Erase 1 char of count */
- - } else {
- -#ifdef TIOCGLTC
- - if (c == ckill || c == cwerase) {
- -#else
- - if (c == ckill) {
- -#endif
- - if (countset == 0)
- - break;
- - countset = 0;
- - } else if (c < '0' || c > '9')
- - break;
- - else {
- - countset = 1;
- - count = (count * 10) + (c - '0');
- - }
- - }
- - if (countset) {
- - (void) sprintf(p, "%ld", count);
- - } else {
- - *p = '\0';
- - count = 0;
- - }
- - }
- -
- - if (c == '\033') { /* escape */
- - (void) strcat(prompt, "M-");
- - c = vgetc();
- - if (c != cintr)
- - c |= META;
- - }
- - secpr[0] = '\0';
- - if (countset == 0)
- - count = 1;
- - docmd(c, count);
- - if (c != '?' && c != 'H') /* UGGH */
- - prflags &=~ HELPMSG;
- - if (dlinno > hdrstart)
- - prflags &=~ HDRONLY;
- -}
- -
- -
- -/*
- - * Process one command, which has already been typed in.
- - */
- -docmd(c, count)
- -int c;
- -long count;
- -{
- - int i;
- - long nart, Hoffset;
- - char *findhist();
- -
- - switch (c) {
- -
- - /* Show more of current article, or advance to next article */
- - case '\n':
- - case ' ':
- -#ifdef DIGPAGE
- - case 'm':
- -#endif /* DIGPAGE */
- - case '\06': /* Control-F for vi compat */
- - prflags &=~ NOPRT;
- - if (atend)
- - goto next;
- - else if (prflags & HDRONLY) {
- - prflags &=~ HDRONLY;
- - if (hasscroll)
- - dlinno = hdrstart;}
- -#ifdef DIGPAGE
- - else if (endsuba > 0)
- - dlinno = endsuba;
- - else if (c == 'm') {
- - do {
- - if (lastlin >= maxlinno)
- - goto next;
- - else
- - appfile(fp, lastlin + 1);
- - } while(strncmp(linebuf, "------------------------", 24)
- - != 0);
- - dlinno = endsuba = lastlin;
- - }
- -#endif
- - else if ((appfile(fp, dlinno + 2 * ARTWLEN), artread)
- - && hasscroll && artlines - dlinno <= ARTWLEN + 2)
- - dlinno = artlines - ARTWLEN;
- - else
- - dlinno += ARTWLEN * count;
- - break;
- -
- - /* No. Go on to next article. */
- - case '.': /* useful if you have a keypad */
- -next: case 'n':
- - readmode = NEXT;
- - FCLOSE(fp);
- - clear(bit);
- - saveart;
- - nextbit();
- - break;
- -
- -
- - /* Back up count pages */
- - case '\b':
- - case '\177':
- - if (dlinno == 0)
- - goto backupone;
- - /* NO BREAK */
- - case META|'v':
- - case '\002': /* Control-B */
- - dlinno -= ARTWLEN * count;
- - if (dlinno < 0)
- - dlinno = 0;
- - break;
- -
- - /* forward half a page */
- - case '\004': /* Control-D, as in vi */
- - if (!atend)
- - dlinno += ARTWLEN/2 * count;
- - break;
- -
- - /* backward half a page */
- - case '\025': /* Control-U */
- - dlinno -= ARTWLEN/2 * count;
- - if (dlinno < 0)
- - dlinno = 0;
- - break;
- -
- - /* forward count lines */
- - case '\016': /* Control-N */
- - case '\005': /* Control-E */
- - dlinno += count;
- - break;
- -
- - /* backwards count lines */
- - case '\020': /* Control-P */
- - case '\031': /* Control-Y */
- - dlinno -= count;
- - if (dlinno < 0)
- - dlinno = 0;
- - break;
- -
- - /* Turn displaying of article back on */
- - case 'l':
- - case 'd':
- - prflags &=~ NOPRT;
- - break;
- -
- - /* display header */
- - case 'h':
- - dlinno = hdrstart;
- - prflags |= HDRONLY;
- - prflags &=~ NOPRT;
- - break;
- -
- - /*
- - * Unsubscribe to the newsgroup and go on to next group
- - */
- -
- - case 'U':
- - case 'u':
- - strcat(prompt, "u");
- - c = vgetc();
- - if (c == 'g') {
- - obit = -1;
- - FCLOSE(fp);
- - zapng = TRUE;
- - saveart;
- - if (nextng()) {
- - if (actdirect == BACKWARD)
- - msg("Can't back up.");
- - else
- - quitflg = 1; /* probably unnecessary */
- - }
- - } else {
- - if (c != cintr && c != ckill)
- - beep();
- - msg("Illegal command");
- - }
- - break;
- -
- - /* Print the current version of news */
- - case 'v':
- - msg("News version: %s", news_version);
- - break;
- -
- -
- - /* Decrypt joke. Always does rot 13 */
- - case 'D':
- - appfile(fp, 32767);
- - for (i = hdrend ; i < artlines ; i++) {
- - register char ch, *p;
- - tfget(linebuf, i);
- - for (p = linebuf ; (ch = *p) != '\0' ; p++) {
- - if (ch >= 'a' && ch <= 'z')
- - *p = (ch - 'a' + 13) % 26 + 'a';
- - else if (ch >= 'A' && ch <= 'Z')
- - *p = (ch - 'A' + 13) % 26 + 'A';
- - }
- - tfput(linebuf, i);
- - }
- - prflags |= NEWART;
- - prflags &=~ (HDRONLY|NOPRT);
- - break;
- -
- - /* write out the article someplace */
- - /* w writes out without the header */
- - case 's':
- - case 'w': {
- - char *grn = groupdir;
- - int wflags;
- -
- - msg("file: ");
- - curflag = CURP2;
- - while ((wflags = vgetc()) == ' ');
- - if (wflags == cintr) {
- - secpr[0] = '\0';
- - break;
- - }
- - if (wflags == '|') {
- - linebuf[0] = '|';
- - if (prget("| ", linebuf+1))
- - break;
- - } else {
- - pushback(wflags);
- - if (prget("file: ", linebuf))
- - break;
- - }
- - wflags = 0;
- - if (c == 's')
- - wflags |= SVHEAD;
- - if (count != 1)
- - wflags |= OVWRITE;
- - bptr = linebuf;
- - while( *bptr == ' ')
- - bptr++; /* strip leading spaces */
- -
- - if (*bptr != PIPECHAR && *bptr != '/') {
- - char hetyped[BUFLEN];
- - char *boxptr;
- - (void) strcpy(hetyped, bptr);
- - if (hetyped[0] == '~' && hetyped[1] == '/') {
- - strcpy(hetyped, bptr+2);
- - strcpy(bptr, userhome);
- - } else if (boxptr = getenv("NEWSBOX")) {
- - if (index(boxptr, '%')) {
- - struct stat stbf;
- - sprintf(bptr, boxptr, grn);
- - if (stat(bptr,&stbf) < 0) {
- - if (mkdir(bptr, 0777) < 0) {
- - msg("Cannot create directory %s", bptr);
- - break;
- - }
- - } else if ((stbf.st_mode&S_IFMT) != S_IFDIR) {
- - msg("%s not a directory", bptr);
- - break;
- - }
- - } else
- - strcpy(bptr, boxptr);
- - } else
- - bptr[0] = '\0';
- -
- - if (bptr[0])
- - (void) strcat(bptr, "/");
- - if (hetyped[0] != '\0')
- - (void) strcat(bptr, hetyped);
- - else
- - (void) strcat(bptr, "Articles");
- - }
- - vsave(bptr, wflags);
- - break;
- - }
- -
- - /* back up */
- - case '-':
- -caseminus:
- - aabs = TRUE;
- - if (!*ofilename1) {
- - msg("Can't back up.");
- - break;
- - }
- - FCLOSE(fp);
- - hptr = h;
- - h = hold;
- - hold = hptr;
- - (void) strcpy(bfr, filename);
- - (void) strcpy(filename, ofilename1);
- - (void) strcpy(ofilename1, bfr);
- - obit = bit;
- - if (strcmp(groupdir, ogroupdir)) {
- - (void) strcpy(bfr, groupdir);
- - selectng(ogroupdir, FALSE, FALSE);
- - (void) strcpy(groupdir, ogroupdir);
- - (void) strcpy(ogroupdir, bfr);
- - ngrp = 1;
- - back();
- - }
- - bit = oobit;
- - oobit = obit;
- - obit = -1;
- - getnextart(TRUE);
- - break;
- -
- - /* skip forwards */
- - case '+':
- - case '=':
- -caseplus: if (count == 0)
- - break;
- - saveart;
- - last = bit;
- - for (i = 0; i < count; i++) {
- - nextbit();
- - if ((bit > pngsize) || (rflag && bit < 1))
- - break;
- - }
- - FCLOSE(fp);
- - obit = -1;
- - break;
- -
- - /* exit - time updated to that of most recently read article */
- - case 'q':
- - quitflg = 1;
- - break;
- -
- - case 'x':
- - xxit(0);
- - break;
- -
- - /* cancel the article. */
- - case 'c':
- - strcpy(prompt, "cancel [n]? ");
- - if (vgetc() != 'y') {
- - msg("Article not cancelled");
- - break;
- - }
- - cancel_command();
- - break;
- -
- - /* escape to shell */
- - case '!': {
- - register char *p;
- - int flags;
- -
- - p = linebuf;
- - if (prget("!", p))
- - break;
- - flags = CWAIT;
- - if (*p == '\0') {
- - (void) strcpy(linebuf, SHELL);
- - flags = 0;
- - }
- - while (*p) p++;
- - while (p > linebuf && p[-1] == ' ')
- - p--;
- - if (*--p == '&') {
- - *p = '\0';
- - flags = BKGRND;
- - } else if (*p == '|') {
- - *p = '\0';
- - (void) sprintf(bfr, "(%s)|mail '%s'", linebuf, username);
- - (void) strcpy(linebuf, bfr);
- - flags |= BKGRND;
- - } else {
- - prflags |= NOPRT;
- - }
- - shcmd(linebuf, flags);
- - break;
- - }
- -
- - /* mail reply */
- - case 'r':
- - reply(FALSE);
- - break;
- -
- - case 'R':
- - reply(TRUE);
- - break;
- -
- - case META|'r':
- - direct_reply();
- - break;
- -
- - /* next newsgroup */
- - case 'N':
- - FCLOSE(fp);
- - if (next_ng_command())
- - quitflg = 1;
- - break;
- -
- - /* mark the rest of the articles in this group as read */
- - case 'K':
- - saveart;
- - while (bit <= ngsize && bit >= minartno) {
- - clear(bit);
- - nextbit();
- - }
- - FCLOSE(fp);
- - break;
- -
- - /* Print the full header */
- - case 'H':
- - if (fp == NULL) {
- - msg("No current article");
- - break;
- - }
- - move(ARTWIN, 0);
- - Hoffset = ftell(fp);
- - (void) fseek(fp, 0L, 0);
- - for (i = 0; i < ARTWLEN; i++) {
- - if (fgets(linebuf, COLS, fp) == NULL)
- - break;
- - if (linebuf[0] == '\n')
- - break;
- - linebuf[COLS] = '\0';
- - addstr(linebuf);
- - }
- - (void) fseek(fp, Hoffset, 0);
- - for(; i < ARTWLEN; i++)
- - addstr(linebuf);
- - prflags |= HELPMSG|NEWART;
- - break;
- - case 'b': /* backup 1 article */
- -backupone:
- - count = bit - 1;
- - /* NO BREAK */
- -
- - case 'A': /* specific number */
- - if (count > pngsize) {
- - msg("not that many articles");
- - break;
- - }
- - readmode = SPEC;
- - aabs = TRUE;
- - bit = count;
- - obit = -1;
- - FCLOSE(fp);
- - break;
- -
- - /* display parent article */
- - case 'p':
- -#ifdef MYDB
- - if (hasdb && (ptr3 = findparent(h->ident, &nart)) != NULL) {
- - msg("parent: %s/%ld", ptr3, nart); /*DEBUG*/
- - updscr(); /*DEBUG*/
- - goto selectart;
- - }
- -#endif
- - if (h->followid[0] == '\0') {
- - msg("no references line");
- - break;
- - }
- - ptr1 = h->followid + strlen(h->followid);
- - do {
- - ptr2 = ptr1;
- - if (*ptr2 == '\0')
- - ptr1 = rindex(h->followid, ' ');
- - else {
- - *ptr2 = '\0';
- - ptr1 = rindex(h->followid, ' ');
- - *ptr2 = ' ';
- - }
- - } while (ptr1 != NULL && --count > 0);
- - if (ptr1 == NULL)
- - ptr1 = h->followid;
- - else ++ptr1;
- - (void) strncpy(linebuf, ptr1, ptr2 - ptr1);
- - linebuf[ptr2 - ptr1] = '\0';
- - msg("%s", linebuf);
- - curflag = CURP2;
- - updscr(); /* may take this out later */
- - goto searchid;
- - /* specific message ID. */
- - case '<':
- - /* could improve this */
- - linebuf[0] = '<';
- - if (prget("<", linebuf+1))
- - break;
- -searchid: secpr[0] = '\0';
- - if (index(linebuf, '@') == NULL && index(linebuf, '>') == NULL) {
- - ptr1 = linebuf;
- - if (*ptr1 == '<')
- - ptr1++;
- - ptr2 = index(ptr1, '.');
- - if (ptr2 != NULL) {
- - *ptr2++ = '\0';
- - (void) sprintf(bfr, "<%s@%s.UUCP>", ptr2, ptr1);
- - (void) strcpy(linebuf, bfr);
- - }
- - }
- - if (index(linebuf, '>') == NULL)
- - (void) strcat(linebuf, ">");
- -
- - ptr1 = findhist(linebuf);
- - if (ptr1 == NULL) {
- - msg("%s not found", linebuf);
- - break;
- - }
- - ptr2 = index(ptr1, '\t');
- - ptr3 = index(++ptr2, '\t');
- - ptr2 = index(++ptr3, ' ');
- - if (ptr2)
- - *ptr2 = '\0';
- - ptr2 = index(ptr3, '/');
- - if (!ptr2) {
- - if (strcmp(++ptr3, "cancelled") == 0)
- - msg("%s has been cancelled", linebuf);
- - else
- - msg("%s has expired", linebuf);
- - break;
- - }
- - *ptr2++ = '\0';
- - (void) sscanf(ptr2, "%ld", &nart);
- -
- - /*
- - * Go to a given article. Ptr3 specifies the newsgroup
- - * and nart specifies the article number.
- - */
- -#ifdef MYDB
- -selectart:
- -#endif /* MYDB */
- - aabs = TRUE;
- - FCLOSE(fp);
- - saveart;
- - (void) strcpy(ogroupdir, ptr3);
- - if (strcmp(groupdir, ogroupdir)) {
- - (void) strcpy(bfr, groupdir);
- - selectng(ogroupdir, TRUE, PERHAPS);
- - (void) strcpy(groupdir, ogroupdir);
- - (void) strcpy(ogroupdir, bfr);
- - ngrp = 1;
- - back();
- - }
- - bit = nart;
- - oobit = obit;
- - obit = -1;
- - getnextart(TRUE);
- - if (bit != nart || strcmp(groupdir, ptr3) != 0) {
- - msg("can't read %s/%ld", ptr3, nart);
- - goto caseminus;
- - }
- - rfq = 0;
- - break;
- -
- - /* follow-up article */
- - case 'f':
- - if (strcmp(h->followto, "poster") == 0) {
- - reply(FALSE);
- - break;
- - }
- - (void) sprintf(bfr, "%s/%s %s", BIN, "postnews", goodone);
- - shcmd(bfr, CWAIT);
- - break;
- -
- - /* erase - pretend we haven't seen this article. */
- - case 'e':
- - erased = 1;
- - set(bit);
- - goto caseplus; /* skip this article for now */
- -
- - case '#':
- - msg("Article %ld of %ld", rfq ? oobit : bit, pngsize);
- - break;
- -
- - /* error */
- - case '?':
- - {
- - FILE *helpf;
- - (void) sprintf(linebuf, "%s/vnews.help", LIB);
- - if ((helpf = fopen(linebuf, "r")) == NULL) {
- - msg("Can't open help file");
- - break;
- - }
- - move(ARTWIN, 0);
- - while (fgets(linebuf, LBUFLEN, helpf) != NULL)
- - addstr(linebuf);
- - (void) fclose(helpf);
- - prflags |= HELPMSG|NEWART;
- - }
- - break;
- -
- - default:
- - if (c != ckill && c != cintr && c != cerase)
- -#ifdef TIOCGLTC
- - if (c != cwerase)
- -#endif
- - {
- - beep();
- - msg("Illegal command");
- - }
- - break;
- - }
- -}
- -
- -cancel_command()
- -{
- - int notauthor;
- -
- - tfilename = filename;
- - (void) strcpy(rcbuf, h->path);
- - ptr1 = index(rcbuf, ' ');
- - if (ptr1)
- - *ptr1 = 0;
- - notauthor = strcmp(username, rcbuf);
- - if (uid != ROOTID && uid && notauthor) {
- - msg("Can't cancel what you didn't write.");
- - return;
- - }
- - if (!cancel(stderr, h, notauthor)) {
- - clear(bit);
- - saveart;
- - nextbit();
- - obit = -1;
- - fp = NULL;
- - }
- - FCLOSE(fp);
- -}
- -/*
- - * Generate replies
- - */
- -
- -reply(include)
- - int include;
- -{
- - char *arg[4];
- - register FILE *rfp;
- - char subj[132];
- - register char *p;
- - char *replyname();
- - struct stat statb;
- - time_t creatm;
- -
- - /* Put the user in the editor to create the body of the reply. */
- - ed = getenv("EDITOR");
- - if (ed == NULL || *ed == '\0')
- - ed = DFTEDITOR;
- - if (ed == NULL) {
- - msg("You don't have an editor");
- - return;
- - }
- -
- - arg[0] = "/bin/sh";
- - arg[1] = "-c";
- -
- - (void) strcpy(tf, tft);
- - (void) mktemp(tf);
- - (void) close(creat(tf,0600));
- - if ((rfp = fopen(tf, "w")) == NULL) {
- - msg("Can't create %s", tf) ;
- - return;
- - }
- - (void) strcpy(subj, h->title);
- - if (!prefix(subj, "Re:")){
- - (void) strcpy(bfr, subj);
- - (void) sprintf(subj, "Re: %s", bfr);
- - }
- -
- - p = replyname(h);
- - fprintf(rfp, "To: %s\n", p);
- - fprintf(rfp, "Subject: %s\n", subj);
- - fprintf(rfp, "In-reply-to: your article %s\n", h->ident);
- -#ifdef INTERNET
- - fprintf(rfp, "News-Path: %s\n", h->path);
- -#endif /* INTERNET */
- - (void) sprintf(rcbuf, "%s -t < %s; rm -f %s", MAILPARSER, tf, tf);
- - putc('\n', rfp);
- - if (include) {
- - FILE *of;
- - char buf[BUFSIZ];
- -
- - of = xart_open(goodone, "r");
- - while (fgets(buf, sizeof buf, of) != NULL)
- - if (buf[0] == '\n')
- - break;
- - while (fgets(buf, sizeof buf, of) != NULL)
- - fprintf(rfp, "> %s", buf);
- - fclose(of);
- - putc('\n', rfp);
- - }
- - fflush(rfp);
- - (void) fstat(fileno(rfp), &statb);
- - creatm = statb.st_mtime;
- - (void) fclose(rfp);
- -
- - (void) sprintf(edcmdbuf, "exec %s %s", ed, tf);
- - arg[2] = edcmdbuf;
- - arg[3] = NULL;
- - if (prun(arg, 0) != 0) {
- - msg("Couldn't run editor");
- - (void) unlink(tf);
- - return;
- - }
- -
- - if (access(tf, 4) || stat(tf, &statb)) {
- - msg("No input file - mail not sent");
- - (void) unlink(tf);
- - return;
- - }
- - if (statb.st_mtime == creatm || statb.st_size < 5) {
- - msg("File unchanged - no message posted");
- - (void) unlink(tf);
- - return;
- - }
- -
- - arg[2] = rcbuf;
- - arg[3] = NULL;
- - prun(arg, BKGRND);
- - prflags |= NOPRT;
- -}
- -
- -direct_reply()
- -{
- - register char *p;
- - register char *q;
- - char *arg[4];
- - char address[PATHLEN];
- - extern char *replyname();
- - extern char *getenv();
- -
- - arg[0] = "/bin/sh";
- - arg[1] = "-c";
- - p = replyname(h);
- - q = address;
- - while (*p != '\0') {
- - if (index("\"\\$", *p) != 0)
- - *q++ = '\\';
- - *q++ = *p++;
- - }
- - *q++ = '\0';
- - if ((MAILER = getenv("MAILER")) == NULL)
- - MAILER = "mail";
- - sprintf(rcbuf, MAILER, hptr->title);
- - sprintf(bfr, "%s %s", rcbuf, address);
- - arg[2] = bfr;
- - arg[3] = NULL;
- - if (prun(arg, 0) != 0) {
- - msg("Couldn't run mailer");
- - return;
- - }
- - prflags |= NOPRT;
- -}
- -
- -next_ng_command()
- -{
- - obit = -1;
- - if (prget("group? ", linebuf))
- - return FALSE;
- - bptr = linebuf;
- - if (!*bptr || *bptr == '-') {
- - if (*bptr)
- - actdirect = BACKWARD;
- - saveart;
- - if (nextng()) {
- - if (actdirect == BACKWARD)
- - msg("Can't back up.");
- - else
- - return TRUE;
- - }
- - return FALSE;
- - }
- - while (isspace(*bptr))
- - bptr++;
- - if (!validng(bptr)) {
- - msg("No such group.");
- - return FALSE;
- - }
- - saveart;
- - back();
- - selectng(bptr, TRUE, TRUE);
- - return FALSE;
- -}
- -
- -/*
- - * Find the next article we want to consider, if we're done with
- - * the last one, and show the header.
- - */
- -getnextart(minus)
- -int minus;
- -{
- - int noaccess;
- - register DIR *dirp;
- - register struct direct *dir;
- - long nextnum, tnum;
- - long atol();
- -
- - noaccess = 0;
- - if (minus)
- - goto nextart2; /* Kludge for "-" command. */
- -
- - if (bit == obit) /* Return if still on same article as last time */
- - return 0;
- -
- -nextart:
- - if (news) {
- - curflag = CURHOME;
- - _amove(0, 0);
- - vflush();
- - }
- - dgest = 0;
- -
- - /* If done with this newsgroup, find the next one. */
- - while (ngsize <= 0 || (!rflag && ((long) bit > ngsize)) || (rflag && bit < minartno)) {
- - if (nextng()) {
- - if (actdirect == BACKWARD) {
- - msg("Can't back up.");
- - actdirect = FORWARD;
- - continue;
- - }
- - else /* if (rfq++ || pflag || cflag) */
- - return 1;
- - }
- - if (rflag)
- - bit = ngsize + 1;
- - else
- - bit = -1;
- - noaccess = 2;
- - }
- -
- - /* speed things up by not searching for article -1 */
- - if (bit < 0) {
- - bit = minartno - 1;
- - nextbit();
- - aabs = FALSE;
- - goto nextart;
- - }
- -
- -nextart2:
- - if (rcreadok)
- - rcreadok = 2; /* have seen >= 1 article */
- - (void) sprintf(filename, "%s/%ld", dirname(groupdir), bit);
- - if (rfq && goodone[0]) /* ??? */
- - strcpy(filename, goodone);
- - if (SigTrap == SIGHUP)
- - return 1;
- - /* Decide if we want to show this article. */
- - if ((fp = art_open(filename, "r")) == NULL) {
- - /* since there can be holes in legal article numbers, */
- - /* we wait till we hit 5 consecutive bad articles */
- - /* before we haul off and scan the directory */
- - if (++noaccess < 5)
- - goto badart;
- - noaccess = 0;
- - dirp = opendir(dirname(groupdir));
- - if (dirp == NULL) {
- - if (errno != EACCES)
- - msg("Can't open %s", dirname(groupdir));
- - goto nextart;
- - }
- - nextnum = rflag ? minartno - 1 : ngsize + 1;
- - while ((dir = readdir(dirp)) != NULL) {
- - if (!dir->d_ino)
- - continue;
- - tnum = atol(dir->d_name);
- - if (tnum <= 0)
- - continue;
- - if (rflag ? (tnum > nextnum && tnum < bit)
- - : (tnum < nextnum && tnum > bit))
- - nextnum = tnum;
- - }
- - closedir(dirp);
- - if (rflag ? (nextnum >= bit) : (nextnum <= bit))
- - goto badart;
- - do {
- - clear(bit);
- - nextbit();
- - } while (rflag ? (nextnum < bit) : (nextnum > bit));
- - obit = -1;
- - aabs = FALSE;
- - goto nextart;
- - } else
- - noaccess = 0;
- -
- - if (hread(h, fp, TRUE) == NULL || (!rfq && !aselect(h, aabs))) {
- -badart:
- - FCLOSE(fp);
- - clear(bit);
- - obit = -1;
- - nextbit();
- - aabs = FALSE;
- - goto nextart;
- - }
- - aabs = FALSE;
- - actdirect = FORWARD;
- - news = TRUE;
- - artbody = ftell(fp);
- - fmthdr();
- - artlines = lastlin;
- - artread = 0;
- - prflags |= NEWART;
- - prflags &=~ NOPRT;
- - if (! cflag && hdrend < ARTWLEN && !cflag)
- - prflags |= HDRONLY;
- - dlinno = 0;
- - maxlinno = NLINES(h, fp);
- - erased = 0;
- -
- - obit = bit;
- - return 0;
- -}
- -
- -/*
- - * Print out whatever the appropriate header is
- - */
- -fmthdr() {
- - char *briefdate();
- - static FILE *ngfd = NULL;
- - static int triedopen = 0;
- - char pbuf[BUFLEN], *printbuffer = groupdir;
- -
- - lastlin = 0;
- - if (ngrp) {
- - pngsize = ngsize;
- - ngrp--;
- - if (!hflag) {
- - if (!triedopen) {
- - (void) sprintf(pbuf,"%s/newsgroups", LIB);
- - ngfd = fopen(pbuf, "r");
- - triedopen++;
- - }
- - if (ngfd != NULL) {
- - register char *p;
- - char ibuf[BUFLEN];
- - rewind(ngfd);
- - while (fgets(ibuf, BUFLEN, ngfd) != NULL) {
- - p = index(ibuf, '\t');
- - if (p)
- - *p++ = '\0';
- - if (strcmp(ibuf, groupdir) == 0) {
- - register char *q;
- - q = rindex(p, '\t');
- - if (q) {
- - p = q;
- - *p++ = '\0';
- - }
- - if (p) {
- - q = index(p, '\n');
- - if (q)
- - *q = '\0';
- - if (*--q == '.')
- - *q = '\0';
- - (void) sprintf(pbuf,"%s (%s)",
- - groupdir, p);
- - printbuffer = pbuf;
- - }
- - break;
- - }
- - }
- - }
- - (void) sprintf(linebuf, "Newsgroup %s", printbuffer);
- - tfappend(linebuf);
- - }
- - }
- - hdrstart = lastlin;
- - if (!hflag) {
- - (void) sprintf(linebuf, "Article %s %s",
- - h->ident, briefdate(h->subdate));
- - tfappend(linebuf);
- - }
- - xtabs(h);
- - vhprint(h, pflag ? 1 : 0);
- - (void) sprintf(linebuf, "(%d lines)", NLINES(h, fp)); tfappend(linebuf);
- - tfappend("");
- - hdrend = lastlin;
- -}
- -
- -/*
- - * Grow tabs into spaces in header fields, 'cause the rest of this
- - * lax program drops turds all over tabs (so it does with \b's, but ..)
- - */
- -xtabs(p)
- -register struct hbuf *p;
- -{
- - xtabf(p->from, sizeof p->from);
- - xtabf(p->path, sizeof p->path);
- - xtabf(p->nbuf, sizeof p->nbuf);
- - xtabf(p->title, sizeof p->title);
- - xtabf(p->ident, sizeof p->ident);
- - xtabf(p->replyto, sizeof p->replyto);
- - xtabf(p->followid, sizeof p->followid);
- - xtabf(p->subdate, sizeof p->subdate);
- - xtabf(p->expdate, sizeof p->expdate);
- - xtabf(p->ctlmsg, sizeof p->ctlmsg);
- - xtabf(p->sender, sizeof p->sender);
- - xtabf(p->followto, sizeof p->followto);
- - xtabf(p->distribution, sizeof p->distribution);
- - xtabf(p->organization, sizeof p->organization);
- - xtabf(p->numlines, sizeof p->numlines);
- - xtabf(p->keywords, sizeof p->keywords);
- - xtabf(p->summary, sizeof p->summary);
- - xtabf(p->approved, sizeof p->approved);
- - xtabf(p->nf_id, sizeof p->nf_id);
- - xtabf(p->nf_from, sizeof p->nf_from);
- -#ifdef DOXREFS
- - xtabf(p->xref, sizeof p->xref);
- -#endif /* DOXREFS */
- -}
- -
- -xtabf(s, size)
- -char *s;
- -int size;
- -{
- - register char *p, *str;
- - register c, i;
- - char buf[LBUFLEN];
- -
- - str = s;
- - if (index(str, '\t') == NULL)
- - return;
- - i = 0;
- - for (p = buf; c = *str++; i++) {
- - if (c == '\t') {
- - *p++ = ' ';
- - if ((i & 7) != 7)
- - str--;
- - } else if (c == '\n') {
- - i = -1;
- - *p++ = c;
- - } else
- - *p++ = c;
- - }
- - *p = '\0';
- - strncpy(s, buf, size - 1);
- -}
- -
- -/*
- - * Print the file header to the temp file.
- - */
- -vhprint(hp, verbose)
- -register struct hbuf *hp;
- -int verbose;
- -{
- - register char *p1, *p2;
- - char fname[BUFLEN];
- - char *tailpath();
- -
- - fname[0] = '\0'; /* init name holder */
- -
- - p1 = index(hp->from, '('); /* Find the sender's full name. */
- - if (p1 == NULL && hp->path[0])
- - p1 = index(hp->path, '(');
- - if (p1 != NULL) {
- - (void) strcpy(fname, p1+1);
- - p2 = index(fname, ')');
- - if (p2 != NULL)
- - *p2 = '\0';
- - }
- -
- - (void) sprintf(linebuf, "Subject: %s", hp->title);
- - tfappend(linebuf);
- - if (!hflag && hp->summary[0])
- - (void) sprintf(linebuf, "Summary: %s", hp->summary), tfappend(linebuf);
- - if (!hflag && hp->keywords[0])
- - (void) sprintf(linebuf, "Keywords: %s", hp->keywords), tfappend(linebuf);
- - if (verbose) {
- - (void) sprintf(linebuf, "From: %s", hp->from); tfappend(linebuf);
- - (void) sprintf(linebuf, "Path: %s", hp->path); tfappend(linebuf);
- - if (hp->organization[0]) {
- - (void) sprintf(linebuf, "Organization: %s", hp->organization);
- - tfappend(linebuf);
- - }
- - }
- - else {
- - if (p1 != NULL)
- - *--p1 = '\0'; /* bump over the '(' */
- -#ifdef INTERNET
- - /*
- - * Prefer Path line if it's in internet format, or if we don't
- - * understand internet format here, or if there is no reply-to.
- - */
- - (void) sprintf(linebuf, "From: %s", hp->from);
- -#else
- - (void) sprintf(linebuf, "Path: %s", tailpath(hp));
- -#endif
- - if (fname[0] || (hp->organization[0] && !hflag)) {
- - (void) strcat(linebuf, " (");
- - if (fname[0] == '\0') {
- - (void) strcpy(fname, hp->from);
- - p2 = index(fname,'@');
- - if (p2)
- - *p2 = '\0';
- - }
- - (void) strcat(linebuf, fname);
- - if (hp->organization[0] && !hflag) {
- - (void) strcat(linebuf, " @ ");
- - (void) strcat(linebuf, hp->organization);
- - }
- - (void) strcat(linebuf, ")");
- - }
- - tfappend(linebuf);
- - if (p1 != NULL)
- - *p1 = ' ';
- - if (hp->ctlmsg[0]) {
- - (void) sprintf(linebuf, "Control: %s", hp->ctlmsg);
- - tfappend(linebuf);
- - }
- - }
- -
- - if (verbose) {
- - (void) sprintf(linebuf, "Newsgroups: %s", hp->nbuf); tfappend(linebuf);
- - (void) sprintf(linebuf, "Date: %s", hp->subdate); tfappend(linebuf);
- - if (hp->sender[0]) {
- - (void) sprintf(linebuf, "Sender: %s", hp->sender);
- - tfappend(linebuf);
- - }
- - if (hp->replyto[0]) {
- - (void) sprintf(linebuf, "Reply-To: %s", hp->replyto);
- - tfappend(linebuf);
- - }
- - if (hp->followto[0]) {
- - (void) sprintf(linebuf, "Followup-To: %s", hp->followto);
- - tfappend(linebuf);
- - }
- - }
- - else if (strcmp(hp->nbuf, groupdir) != 0) {
- - (void) sprintf(linebuf, "Newsgroups: %s", hp->nbuf);
- - tfappend(linebuf);
- - timer();
- - }
- -}
- -
- -#ifdef MYDB
- -
- -char *
- -findparent(id, num)
- -char *id;
- -long *num;
- -{
- - struct artrec a;
- - char idbuf[BUFSIZE];
- - char *ngname();
- -
- - strcpy(idbuf, id);
- - lcase(idbuf);
- -
- - if (lookart(id, &a) == DNULL)
- - return NULL;
- - if (a.parent == DNULL)
- - return NULL;
- - readrec(a.parent, &a);
- - *num = a.groups[0].artno;
- - return ngname(a.groups[0].newsgroup);
- -}
- -
- -#endif
- -
- -
- -/*
- - * Append file to temp file, handling control characters, folding lines, etc.
- - * We don't grow the temp file to more than nlines so that a user won't have
- - * to wait for 20 seconds to read in a monster file from net.sources.
- - * What we really want is coroutines--any year now.
- - */
- -
- -#define ULINE 0200
- -static char *maxcol;
- -
- -appfile(iop, nlines)
- -register FILE *iop;
- -{
- - register int c;
- - register char *icol; /* &linebuf[0] <= icol <= maxcol */
- -
- - if (artread || artlines >= nlines || iop == NULL)
- - return;
- - maxcol = linebuf;
- - icol = linebuf;
- - while ((c = getc(iop)) != EOF) {
- - switch (c) {
- - case ' ':
- - if (icol == maxcol && icol < linebuf + LBUFLEN - 1) {
- - *icol++ = ' ';
- - maxcol = icol;
- - } else {
- - if (*icol == '_')
- - *icol++ = ULINE | ' ';
- - else
- - icol++;
- - }
- - break;
- - case '\t':
- - icol = (icol - linebuf &~ 07) + 8 + linebuf;
- - growline(icol);
- - break;
- - case '\b':
- - if (icol > linebuf) --icol;
- - break;
- - case '\n':
- - outline();
- - if (artlines >= nlines)
- - return;
- - icol = linebuf;
- - break;
- - case '\r':
- - icol = linebuf;
- - break;
- - case '\f':
- - outline(); outline(); outline();
- - if (artlines >= nlines)
- - return;
- - icol = linebuf;
- - break;
- - default:
- - if (c < ' ' || c > '~')
- - break;
- - else if (icol >= linebuf + LBUFLEN - 1)
- - icol++;
- - else if (icol == maxcol) {
- - *icol++ = c;
- - maxcol = icol; }
- - else if (c == '_')
- - *icol++ |= ULINE;
- - else if (*icol == '_')
- - *icol++ = (c | ULINE);
- - else *icol++ = c;
- - break;
- - }
- - }
- - if (maxcol != linebuf) /* file not terminated with newline */
- - outline();
- - artread++;
- -}
- -
- -growline(col)
- -char *col;
- -{
- - while (maxcol < col && maxcol < linebuf + LBUFLEN - 1)
- - *maxcol++ = ' ';
- -}
- -
- -outline()
- -{
- - *maxcol = '\0';
- - if (strncmp(linebuf, ">From ", 6) == 0) {
- - register char *p;
- - for (p = linebuf ; (*p = p[1]) != '\0' ; p++);
- - }
- - tfappend(linebuf);
- - if (maxcol > linebuf)
- - artlines = lastlin;
- - maxcol = linebuf;
- -}
- -
- -prget(prompter, buf)
- -char *prompter, *buf;
- -{
- - char *p, *q, *r;
- - int c, lastc;
- -
- - curflag = CURP2;
- - r = buf;
- - lastc = '\0';
- - for (;;) {
- - *r = '\0';
- - p = secpr;
- - for (q = prompter ; *q ; q++)
- - *p++ = *q;
- - for (q = buf ; *q ; q++) {
- - if (p < &secpr[SECPRLEN-1] && *q >= ' ' && *p <= '~')
- - *p++ = *q;
- - }
- - *p = '\0';
- - c = vgetc();
- - if (c == '\n' || c == cintr) {
- - break;
- - }
- - if (c == cerase || c == '\b' || c == '\177') {
- - if (lastc == '\\')
- - r[-1] = c;
- - else if (r > buf)
- - r--;
- - } else if (c == ckill) {
- - if (lastc == '\\')
- - r[-1] = c;
- - else
- - r = buf;
- -#ifdef TIOCGLTC
- - } else if (c == cwerase) {
- - if (lastc == '\\')
- - r[-1] = c;
- - else {
- - while (r > buf && (r[-1] == ' ' || r[-1] == '\t'))
- - r--;
- - while (r > buf && r[-1] != ' ' && r[-1] != '\t')
- - r--;
- - }
- -#endif
- - } else {
- - *r++ = c;
- - }
- - lastc = c;
- - }
- - curflag = CURHOME;
- - secpr[0] = '\0';
- - return (c == cintr);
- -}
- -
- -
- -
- -/*
- - * Execute a shell command.
- - */
- -
- -shcmd(cmd, flags)
- -char *cmd;
- -{
- - char *arg[4];
- -
- - arg[0] = SHELL, arg[1] = "-c", arg[2] = cmd, arg[3] = NULL;
- - return prun(arg, flags);
- -}
- -
- -
- -prun(args, flags)
- -char **args;
- -{
- - int pid;
- - int i;
- - int (*savequit)();
- - char *env[100], **envp, **oenvp;
- - char a[BUFLEN + 2];
- - extern char **environ;
- - int pstatus, retval;
- -
- - if (!(flags & BKGRND)) {
- - botscreen();
- - ttycooked();
- -#ifdef SIGTSTP
- - (void) signal(SIGTSTP, SIG_DFL);
- - (void) signal(SIGTTIN, SIG_DFL);
- - (void) signal(SIGTTOU, SIG_DFL);
- -#endif
- - }
- -#ifdef BSD4_2
- - while ((pid = vfork()) == -1)
- -#else /* !BSD4_2 */
- - /* 4.1 BSD (at least) can't handle this vfork with -ljobs */
- - while ((pid = fork()) == -1)
- -#endif /* !BSD4_2 */
- - sleep(1); /* must not clear alarm */
- - if (pid == 0) {
- - for (i = 3 ; i < 20 ; i++)
- - close(i);
- - if (flags & BKGRND) {
- - (void) signal(SIGINT, SIG_IGN);
- - (void) signal(SIGQUIT, SIG_IGN);
- -#ifdef SIGTSTP
- - (void) signal(SIGTSTP, SIG_IGN);
- - (void) signal(SIGTTIN, SIG_IGN);
- - (void) signal(SIGTTOU, SIG_IGN);
- -#endif
- - (void) close(0);
- - (void) close(1);
- - (void) open("/dev/null", 2);
- - (void) dup(0);
- - }
- - /* set $A */
- - (void) sprintf(a, "A=%s", filename);
- - oenvp = environ;
- - env[0] = a;
- - for (envp = env + 1 ; *oenvp != NULL && envp < env + 98 ; oenvp++)
- - if ((*oenvp)[0] != 'A' || (*oenvp)[1] != '=')
- - *envp++ = *oenvp;
- - *envp = NULL;
- -
- - (void) umask(savmask);
- - execve(args[0], args, env);
- - perror(args[0]);
- - exit(20);
- - }
- - if (!(flags & BKGRND)) {
- - savequit = signal(SIGQUIT, SIG_IGN);
- - while ((i = wait(&pstatus)) != pid && (i != -1 || errno == EINTR))
- - ;
- - if (i == -1)
- - retval = 1;
- - else
- - retval = pstatus;
- - if (flags & CWAIT) {
- - fprintf(stderr, "[Hit return to continue]");
- - while ((errno = 0, i = getchar()) != '\n'
- - && (i != EOF || errno == EINTR));
- - }
- - (void) signal(SIGQUIT, savequit);
- - ttyraw();
- - clearok(curscr, 1);
- -#ifdef SIGTSTP
- - (void) signal(SIGTSTP, onstop);
- - (void) signal(SIGTTIN, onstop);
- - (void) signal(SIGTTOU, onstop);
- -#endif
- - return retval;
- - } else
- - return 0;
- -}
- -
- -#ifdef DIGPAGE
- -
- -
- -/*
- - * Find end of current subarticle in digest.
- - */
- -
- -findend(l)
- -{
- - register int i, n;
- - register char *p;
- -
- - for (i = l ; i < l + ARTWLEN && i < lastlin ; i++) {
- - tfget(linebuf, i);
- - for (p = linebuf ; *p == '-' ; p++)
- - ;
- - n = (int)p - (int)linebuf;
- - if ( (n > 23 && n < 33) || (n > 65 && n < 79)) {
- - tfget(linebuf, ++i);
- - if (linebuf[0] == '\0')
- - return i + 1;
- - }
- - }
- - return 0;
- -}
- -
- -#endif
- -
- -
- -/*** Routines for handling temporary file ***/
- -
- -/*
- - * Append to temp file.
- - * Long lines are folded.
- - */
- -
- -tfappend(tline)
- -register char *tline;
- -{
- - register char *nxtlin;
- -
- - do {
- - nxtlin = index(tline, '\n');
- - if (nxtlin)
- - *nxtlin++ = '\0';
- -
- - while (strlen(tline) > COLS) {
- - tfput(tline, lastlin++);
- - tline += COLS;
- - maxlinno++;
- - }
- - tfput(tline, lastlin++);
- - } while ((tline = nxtlin) != NULL);
- -}
- -
- -
- -tfput(tline, linno)
- -char *tline;
- -{
- - register char *p;
- - register FILE *rtfp; /* try to make it a little faster */
- - register int i;
- -
- - p = tline, i = even(COLS);
- - tfseek(linno, 1);
- - rtfp = tfp;
- - while (--i >= 0) {
- - if (*p)
- - putc(*p++, rtfp);
- - else
- - putc('\0', rtfp);
- - }
- - tflinno++;
- -}
- -
- -
- -tfget(tline, linno)
- -char *tline;
- -{
- - tfseek(linno, 0);
- - fread(tline, even(COLS), 1, tfp);
- - tline[COLS] = '\0';
- - tflinno++;
- -}
- -
- -
- -tfseek(linno, wrflag)
- -{
- - static int lastwrflag = 1;
- -
- - if (linno != tflinno || wrflag != lastwrflag) {
- - (void) fseek(tfp, (long)linno * even(COLS), 0);
- - tflinno = linno;
- - lastwrflag = wrflag;
- - }
- -}
- -
- -/* VARARGS1 */
- -msg(s, a1, a2, a3, a4)
- -char *s;
- -{
- - (void) sprintf(secpr, s, a1, a2, a3, a4);
- -}
- -
- -
- -/*
- - * Update the display.
- - * The display is entirely controlled by this routine,
- - * which means that this routine may get pretty snarled.
- - */
- -
- -static int savelinno = -1; /* dlinno on last call to updscr */
- -static int savepr; /* prflags on last call */
- -#ifdef TIOCGWINSZ
- -static int UPDATING = 0, WINCH = 0;
- -
- -/*
- - * called by winch() from virtterm.c -- resets state information back
- - * to start-up state and forces a full redraw of the screen. The
- - * current article is rewound to the beginning because it's would
- - * be very difficult to get the screen to return to the exact point
- - * in the file that the user left off (I know, I tried).
- - */
- -winch_upd()
- -{
- - if(UPDATING) /* concurrency. wow! */
- - WINCH++;
- - else if((WINCH == 0) && (savelinno >= 0)) {
- - int saveline = dlinno, saveflag = curflag;
- -
- - /* reread the article */
- - FCLOSE(fp);
- - obit = -1;
- - getnextart(FALSE);
- - appfile(fp, dlinno + ARTWLEN + 1);
- -
- - /* fix up the screen */
- - curflag = saveflag;
- - strcpy(prompt,"more? ");
- - clearok(curscr, 1);
- - updscr();
- - }
- -}
- -#endif /* TIOCGWINSZ */
- -
- -
- -updscr()
- -{
- - int count;
- - int i;
- -
- -#ifdef TIOCGWINSZ
- - UPDATING++;
- -#endif /* TIOCGWINSZ */
- - if (checkin())
- - return;
- - if ((prflags & HELPMSG) == 0
- - && (dlinno != savelinno || savepr != prflags)
- - && quitflg == 0) {
- - if (dlinno != savelinno)
- - prflags &=~ NOPRT;
- - count = ARTWLEN;
- - if (prflags & NOPRT)
- - count = 0;
- - if ((prflags & HDRONLY) && count > hdrend)
- - count = hdrend - dlinno;
- -#ifdef DIGPAGE
- - if (endsuba > 0 && count > endsuba - dlinno)
- - count = endsuba - dlinno;
- -#endif
- - if ((prflags & NEWART) == 0)
- - ushift(ARTWIN, ARTWIN+ARTWLEN-1, dlinno - savelinno);
- - if (count > lastlin - dlinno)
- - count = lastlin - dlinno;
- - for (i = ARTWIN ; i < ARTWIN + ARTWLEN ; i++)
- - clrline(i);
- - for (i = 0 ; i < count ; i++) {
- - tfget(linebuf, dlinno + i);
- - mvaddstr(ARTWIN + i, 0, linebuf);
- - }
- - prflags &=~ NEWART;
- - savepr = prflags;
- - savelinno = dlinno;
- - }
- - clrline(SPLINE), clrline(PRLINE);
- -#ifdef STATTOP
- - mvaddstr(PRLINE, 0, prompt);
- -#else
- - if (strlen(secpr) <= COLS)
- - mvaddstr(PRLINE, 0, prompt);
- -#endif
- - mvaddstr(PRLINE, 59, timestr);
- - mvaddstr(PRLINE, 17, groupdir);
- - addch(' '); addnum(bit); addch('/'); addnum(pngsize); addch(' ');
- - if (ismail)
- - mvaddstr(PRLINE, 75, ismail > 1? "MAIL" : "mail");
- - mvaddstr(SPLINE, 0, secpr);
- - if (curflag == CURP1)
- - move(PRLINE, strlen(prompt));
- - else if (curflag == CURHOME)
- - move(0, 0);
- - refresh();
- -#ifdef TIOCGWINSZ
- - UPDATING=0;
- - if (WINCH) { /* window changed while updating screen */
- - WINCH = 0;
- - winch_upd();
- - }
- -#endif /* TIOCGWINSZ */
- -}
- -
- -addnum(n)
- -register long n;
- -{
- - if (n >= 10)
- - addnum(n / 10);
- - addch((char)(n % 10 + '0'));
- -}
- -
- -/*
- - * Called on alarm signal.
- - * Simply sets flag, signal processed later.
- - */
- -
- -onalarm()
- -{
- -#ifdef SIGTSTP
- - int dojump = reading;
- -
- - reading = FALSE;
- - alflag++;
- - if (dojump)
- - longjmp(alrmjmp, 1);
- -#else /* !SIGTSTP */
- - alflag++;
- -#endif
- -}
- -
- -/*
- - * Process alarm signal (or start clock)
- - */
- -timer()
- -{
- - time_t tod;
- - int hour;
- - int i;
- - struct tm *t;
- - struct stat statb;
- - struct tm *localtime();
- - static char months[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
- - static long oldmsize = 1000000L;
- - static int rccount = 10;
- - static time_t lastismail = 0;
- -
- - alflag = 0;
- - (void) signal(SIGALRM, onalarm);
- - (void) time(&tod);
- - t = localtime(&tod);
- - i = 60 - t->tm_sec;
- - (void) alarm(i > 30? 30 : i); /* reset alarm */
- - hour = t->tm_hour % 12;
- - if (hour == 0) hour = 12;
- - (void) sprintf(timestr, "%.3s %d %d:%02d",
- - months + 3 * t->tm_mon, t->tm_mday, hour, t->tm_min);
- - if (mailf == NULL || stat(mailf, &statb) < 0) {
- - statb.st_size = 0;
- - }
- - if (statb.st_size > oldmsize) {
- - ismail = 2;
- - beep();
- - } else {
- - if (statb.st_size == 0)
- - ismail = 0;
- - /* force MAIL for at least 30 seconds */
- - else if (ismail > 1 && (lastismail+30) < tod)
- - ismail = 1;
- - }
- - oldmsize = statb.st_size;
- - lastismail = tod;
- - if (uflag && !xflag && --rccount < 0) {
- - writeoutrc();
- - if (secpr[0] == '\0')
- - (void) strcpy(secpr, ".newsrc updated");
- - rccount = 10;
- - }
- -}
- -
- -char *
- -getmailname()
- -{
- - static char mailname[32];
- - register char *p;
- -
- - if( (p = getenv("MAIL")) != NULL)
- - return p;
- -#ifndef MMDF
- - if (username[0] == '\0' || strlen(username) > 15)
- - return NULL;
- -#ifdef USG
- - (void) sprintf(mailname, "/usr/mail/%s", username);
- -#else /* !USG */
- - (void) sprintf(mailname, "/usr/spool/mail/%s", username);
- -#endif /* !USG */
- -#else /* MMDF */
- - (void) sprintf(mailname, "%s/mailbox", userhome);
- -#endif /* MMDF */
- - return mailname;
- -}
- -
- -
- -
- -/*** Terminal I/O ***/
- -
- -#define INBUFSIZ 8
- -
- -char inbuf[INBUFSIZ]; /* input buffer */
- -char outbuf[BUFSIZ]; /* output buffer */
- -int innleft = 0; /* # of chars in input buffer */
- -int outnleft = BUFSIZ; /* room left in output buffer */
- -char *innext; /* next input character */
- -char *outnext = outbuf; /* next space in output buffer */
- -#ifdef USG
- -int oflags; /* fcntl flags (for nodelay read) */
- -#endif
- -
- -/*
- - * Input a character
- - */
- -
- -vgetc()
- -{
- - register c;
- -#if defined(BSD4_2) || defined(BSD4_1C)
- - int readfds, exceptfds;
- -#endif
- -
- -recurse:
- - if (--innleft >= 0) {
- - c = *innext++;
- - } else {
- - if (alflag)
- - timer();
- - updscr(); /* update the display */
- - for (;;) {
- - if (innleft > 0 || alflag)
- - goto recurse;
- - intflag = 0;
- -#ifdef USG
- - if (oflags & O_NDELAY) {
- - oflags &=~ O_NDELAY;
- - fcntl(0, F_SETFL, oflags);
- - }
- -#endif
- -#ifdef SIGTSTP
- - if (setjmp(alrmjmp))
- - continue;
- - if (setjmp(intjmp))
- - return cintr;
- - reading = TRUE;
- -#endif /* SIGTSTP */
- -#if defined(BSD4_2) || defined(BSD4_1C)
- - /* Use a select because it can be interrupted. */
- - readfds = 1; exceptfds = 1;
- - select(1, &readfds, (int *)0, &exceptfds, (int *)0);
- - if (!(readfds & 1))
- - break;
- -#endif
- - innleft = read(0, inbuf, INBUFSIZ);
- -#ifdef SIGTSTP
- - reading = FALSE;
- -#endif /* SIGTSTP */
- - if (innleft > 0)
- - break;
- - if (innleft == 0) {
- - quitflg++;
- - return cintr;
- - }
- - if (errno != EINTR)
- - abort(); /* "Can't happen" */
- - if (intflag) {
- - intflag--;
- - return cintr;
- - }
- - }
- - innext = inbuf + 1;
- - innleft--;
- - c = inbuf[0];
- - }
- -#ifndef USG
- -#ifndef CBREAK
- - c &= 0177;
- - if (c == '\034') /* FS character */
- - xxit(0);
- -#endif
- -#endif
- - if (c == '\f') {
- - clearok(curscr, 1);
- - prflags &=~ NOPRT;
- - goto recurse;
- - }
- - if (c == '\r')
- - c = '\n';
- - return c;
- -}
- -
- -
- -/*
- - * Push a character back onto the input stream.
- - */
- -
- -pushback(c)
- -{
- - if (innext <= inbuf)
- - abort();
- - *--innext = c;
- - innleft++;
- -}
- -
- -/*
- - * Check for terminal input
- - */
- -
- -checkin()
- -{
- -#ifdef FIONREAD
- - int count;
- -#endif
- -#ifdef STATTOP
- - if (innleft > 0)
- -#else
- - if (innleft > 0 || alflag)
- -#endif
- - return 1;
- -#if defined(USG) || defined(FIONREAD)
- - if (ospeed >= B9600)
- - return 0;
- - vflush();
- - if (ospeed <= B300)
- - ttyowait();
- -#ifdef USG
- - if ((oflags & O_NDELAY) == 0) {
- - oflags |= O_NDELAY;
- - (void) fcntl(0, F_SETFL, oflags);
- - }
- - if ((innleft = read(0, inbuf, INBUFSIZ)) > 0) {
- - innext = inbuf;
- - return 1;
- - }
- -#endif
- -#ifdef FIONREAD
- - count = 0; /* in case FIONREAD fails */
- - (void) ioctl(0, FIONREAD, (char *)&count);
- - if (count)
- - return 1;
- -#endif
- -#endif
- - return 0;
- -}
- -
- -
- -
- -/*
- - * flush terminal input queue.
- - */
- -
- -clearin()
- -{
- -#ifdef USG
- - (void) ioctl(0, TCFLSH, (char *)0);
- -#else
- -#ifdef TIOCFLUSH
- - (void) ioctl(0, TIOCFLUSH, (char *)0);
- -#else
- - struct sgttyb tty;
- - (void) ioctl(0, TIOCGETP, &tty);
- - (void) ioctl(0, TIOCSETP, &tty);
- -#endif
- -#endif
- - innleft = 0;
- -}
- -
- -vputc(c)
- -{
- - if (--outnleft < 0) {
- - vflush();
- - outnleft--;
- - }
- - *outnext++ = c;
- -}
- -
- -/*
- - * Flush the output buffer
- - */
- -
- -vflush()
- -{
- - register char *p;
- - register int i;
- -#ifdef BSD4_2
- - int mask;
- -#else
- - unsigned oalarm;
- -#endif
- -
- -#ifdef BSD4_2
- - mask = sigblock(1 << (SIGALRM-1));
- -#else
- - oalarm = alarm(0);
- -#endif
- - for (p = outbuf ; p < outnext ; p += i) {
- - if ((i = write(1, p, outnext - p)) < 0) {
- - if (errno != EINTR)
- - abort(); /* "Can't happen" */
- - i = 0;
- - }
- - }
- - outnleft = BUFSIZ;
- - outnext = outbuf;
- -#ifdef BSD4_2
- - sigsetmask(mask);
- -#else
- - (void) alarm(oalarm);
- -#endif
- -}
- -
- -/*** terminal modes ***/
- -
- -#ifdef USG
- -static struct termio oldtty, newtty;
- -
- -/*
- - * Save tty modes
- - */
- -
- -ttysave()
- -{
- - if (ioctl(1, TCGETA, &oldtty) < 0)
- - xerror("Can't get tty modes");
- - newtty = oldtty;
- - newtty.c_iflag &=~ (INLCR|IGNCR|ICRNL);
- - newtty.c_oflag &=~ (OPOST);
- - newtty.c_lflag &=~ (ICANON|ECHO|ECHOE|ECHOK|ECHONL);
- - newtty.c_lflag |= (NOFLSH);
- - newtty.c_cc[VMIN] = 1;
- - newtty.c_cc[VTIME] = 0;
- - cerase = oldtty.c_cc[VERASE];
- - ckill = oldtty.c_cc[VKILL];
- - cintr = oldtty.c_cc[VINTR];
- - ospeed = oldtty.c_cflag & CBAUD;
- - initterm();
- -}
- -
- -
- -/*
- - * Set tty modes for visual processing
- - */
- -
- -ttyraw()
- -{
- - while (ioctl(1, TCSETAF, &newtty) < 0 && errno == EINTR)
- - ;
- - rawterm();
- -}
- -
- -ttyowait()
- -{ /* wait for output queue to drain */
- - while (ioctl(1, TCSETAW, &newtty) < 0 && errno == EINTR)
- - ;
- -}
- -
- -/*
- - * Restore tty modes
- - */
- -
- -ttycooked()
- -{
- - cookedterm();
- - vflush();
- - while (ioctl(1, TCSETAF, &oldtty) < 0 && errno == EINTR)
- - ;
- - oflags &=~ O_NDELAY;
- - (void) fcntl(0, F_SETFL, oflags) ;
- -}
- -
- -#else
- -
- -static struct sgttyb oldtty, newtty;
- -#ifdef TIOCGLTC
- -static struct ltchars oldltchars, newltchars;
- -#endif
- -
- -/*
- - * Save tty modes
- - */
- -
- -ttysave()
- -{
- -#ifdef CBREAK
- - struct tchars tchars; /* special characters, including interrupt */
- -#endif
- -#ifdef SIGTSTP
- - int getpgrp();
- -#if defined(BSD4_2) || defined(BSD4_1C)
- - int tpgrp;
- -#else /* BSD4_1 */
- - short tpgrp;
- -#endif /* BSD4_1 */
- -
- -retry:
- -#ifdef BSD4_2
- - (void) sigblock(sigmask(SIGTSTP)|sigmask(SIGTTIN)|sigmask(SIGTTOU));
- -#else /* !BSD4_2 */
- - (void) signal(SIGTSTP, SIG_HOLD);
- - (void) signal(SIGTTIN, SIG_HOLD);
- - (void) signal(SIGTTOU, SIG_HOLD);
- -#endif /* !BSD4_2 */
- - if (ioctl(2, TIOCGPGRP, (char *)&tpgrp) < 0)
- - goto nottty;
- - if (tpgrp != getpgrp(0)) { /* not in foreground */
- - (void) signal(SIGTTOU, SIG_DFL);
- -#ifdef BSD4_2
- - (void) sigsetmask(sigblock(0) & ~sigmask(SIGTTOU));
- -#endif /* BSD4_2 */
- - (void) kill(0, SIGTTOU);
- - /* job stops here waiting for SIGCONT */
- - goto retry;
- - }
- - (void) signal(SIGTTIN, SIG_DFL);
- - (void) signal(SIGTTOU, SIG_DFL);
- - (void) signal(SIGTSTP, SIG_DFL);
- -#ifdef BSD4_2
- - (void) sigsetmask(sigblock(0) & ~(sigmask(SIGTSTP)|sigmask(SIGTTIN)|sigmask(SIGTTOU)));
- -#endif /* BSD4_2 */
- -#endif /* SIGTSTP */
- - if (ioctl(1, TIOCGETP, (char *)&oldtty) < 0)
- -nottty: xerror("Can't get tty modes");
- - newtty = oldtty;
- - newtty.sg_flags &=~ (CRMOD|ECHO|XTABS);
- -#ifdef CBREAK
- - newtty.sg_flags |= CBREAK;
- - ioctl(1, TIOCGETC, (char *)&tchars);
- - cintr = tchars.t_intrc;
- -#else /* !CBREAK */
- - newtty.sg_flags |= RAW;
- - cintr = '\0177'; /* forcibly this on V6 systems */
- -#endif /* !CBREAK */
- - cerase = oldtty.sg_erase;
- - ckill = oldtty.sg_kill;
- - ospeed = oldtty.sg_ospeed;
- -#ifdef TIOCGLTC
- - if (ioctl(1, TIOCGLTC, (char *)&oldltchars) >= 0) {
- - newltchars = oldltchars;
- - newltchars.t_dsuspc = -1;
- - cwerase = oldltchars.t_werasc;
- - }
- -#endif
- - initterm();
- -#ifdef SIGTSTP
- - (void) signal(SIGTTIN, onstop);
- - (void) signal(SIGTTOU, onstop);
- - (void) signal(SIGTSTP, onstop);
- -#endif /* SIGTSTP */
- -}
- -
- -
- -/*
- - * Set tty modes for visual processing
- - */
- -
- -ttyraw()
- -{
- - while (ioctl(1, TIOCSETN, (char *)&newtty) < 0 && errno == EINTR)
- - ;
- -#ifdef TIOCGLTC
- - if (newltchars.t_dsuspc == '\377')
- - while (ioctl(1, TIOCSLTC, (char *)&newltchars) < 0 && errno == EINTR)
- - ;
- -#endif
- - rawterm();
- -}
- -
- -ttyowait()
- -{ /* wait for output queue to drain */
- -#ifdef TIOCDRAIN /* This ioctl is a local mod on linus */
- - (void) ioctl(1, TIOCDRAIN, (char *)0);
- -#endif
- -}
- -
- -
- -/*
- - * Restore tty modes
- - */
- -
- -ttycooked()
- -{
- - cookedterm();
- - vflush();
- - while (ioctl(1, TIOCSETN, (char *)&oldtty) < 0 && errno == EINTR)
- - ;
- -#ifdef TIOCGLTC
- - if (newltchars.t_dsuspc == '\377')
- - while (ioctl(1, TIOCSLTC, (char *)&oldltchars) < 0 && errno == EINTR)
- - ;
- -#endif
- -}
- -
- -#endif
- -
- -
- -
- -/*** signal handlers ***/
- -
- -onint() {
- -#ifdef SIGTSTP
- - int dojump = reading;
- -
- - reading = FALSE;
- -#endif /* SIGTSTP */
- - if (!news) {
- - ttycooked();
- - xxit(1);
- - }
- - (void) signal(SIGINT, onint);
- - clearin(); /* flush input queue */
- -#ifdef SIGTSTP
- - if (dojump)
- - longjmp(intjmp, 1);
- -#endif /* SIGTSTP */
- - intflag++;
- -}
- -
- -#ifdef SIGTSTP
- -onstop(signo)
- -int signo;
- -{
- - /* restore old terminal state */
- - botscreen();
- - vflush();
- - ttycooked();
- - (void) signal(signo, SIG_DFL);
- -#ifdef BSD4_2
- - (void) sigblock(sigmask(SIGALRM)|sigmask(SIGINT));
- - (void) sigsetmask(sigblock(0) & ~sigmask(signo));
- -#else /* BSD4_1 */
- - (void) alarm(0);
- -#endif /* BSD4_1 */
- - (void) kill(0, signo); /* stop here until continued */
- -
- - (void) signal(signo, onstop);
- - /* restore our special terminal state */
- - ttyraw();
- -#ifdef TIOCGWINSZ
- - winch(); /* get current window size and redraw screen */
- -#endif /* TIOCGWINSZ */
- - clearok(curscr, 1);
- - updscr();
- -#ifdef BSD4_2
- - (void) sigsetmask(sigblock(0) & ~(sigmask(SIGALRM)|sigmask(SIGINT)));
- -#else /* BSD4_1 */
- - timer();
- -#endif /* BSD4_1 */
- -}
- -#endif
- -
- -/*** stolen from rfuncs2.c and modified ***/
- -
- -vsave(to, flags)
- -register char *to;
- -{
- - register FILE *ufp;
- - int isprogram = 0;
- - int isnew = 1;
- - long saveoff;
- - char temp[20];
- - char *fname;
- - char prog[BUFLEN + 24];
- -
- - saveoff = ftell(fp);
- - (void) fseek(fp, artbody, 0);
- - fname = to;
- - if (*to == PIPECHAR) {
- - if (strlen(to) > BUFLEN) {
- - msg("Command name too long");
- - goto out;
- - }
- - flags |= OVWRITE;
- - (void) strcpy(temp, "/tmp/vnXXXXXX");
- - (void) mktemp(temp);
- - fname = temp;
- - _amove(ROWS - 1, 0);
- - vflush();
- - }
- - if ((flags & OVWRITE) == 0) {
- - ufp = fopen(fname, "r");
- - if (ufp != NULL) {
- - (void) fclose(ufp);
- - isnew = 0;
- - }
- - }
- - (void) umask(savmask);
- -
- - if (*to == PIPECHAR)
- - isprogram++;
- - if ((ufp = fopen(fname, (flags & OVWRITE) == 0? "a" : "w")) == NULL) {
- - msg("Cannot open %s", fname);
- - goto out;
- - }
- - /*
- - * V7MAIL code is here to conform to V7 mail format.
- - * If you need a different format to be able to
- - * use your local mail command (such as four ^A's
- - * on the end of articles) substitute it here.
- - */
- - if (flags & SVHEAD) {
- -#ifdef MMDF
- - if (!isprogram)
- - fprintf(ufp, "\001\001\001\001\n");
- -#endif /* MMDF */
- -#ifdef V7MAIL
- - h->subtime = cgtdate(h->subdate);
- - fprintf(ufp, "From %s %s", replyname(h), ctime(&h->subtime));
- -#endif
- - hprint(h, ufp, 2);
- -#ifdef V7MAIL
- - tprint(fp, ufp, TRUE);
- - putc('\n', ufp); /* force blank line at end (ugh) */
- -#else
- - tprint(fp, ufp, FALSE);
- -#endif
- - } else {
- - tprint(fp, ufp, FALSE);
- - }
- -
- - fclose(ufp);
- - if (isprogram) {
- - (void) sprintf(prog, "(%s)<%s", to + 1, fname);
- - shcmd(prog, CWAIT);
- - prflags |= NOPRT;
- - } else {
- - if ((flags & OVWRITE) == 0)
- - msg("file: %s %s", to, isnew ? "created" : "appended");
- - else
- - msg("file: %s written", to);
- - }
- -
- -out:
- - if (isprogram) {
- - (void) unlink(fname);
- - }
- - (void) umask(N_UMASK);
- - (void) fseek(fp, saveoff, 0);
- -}
- -
- -xxit(status)
- -int status;
- -{
- - (void) unlink(infile);
- - (void) unlink(outfile);
- -#ifdef SORTACTIVE
- - if (strncmp(ACTIVE,"/tmp/", 5) == 0)
- - (void) unlink(ACTIVE);
- -#endif /* SORTACTIVE */
- - if (ospeed) { /* is == 0, we haven't been in raw mode yet */
- - botscreen();
- - vflush();
- - ttycooked();
- - }
- - exit(status);
- -}
- *-*-END-of-src/visual.c-*-*
- echo x - src/recmail.c 1>&2
- sed 's/.//' >src/recmail.c <<'*-*-END-of-src/recmail.c-*-*'
- -/*
- - * This software is Copyright (c) 1986 by Rick Adams.
- - *
- - * Permission is hereby granted to copy, reproduce, redistribute or
- - * otherwise use this software as long as: there is no monetary
- - * profit gained specifically from the use or reproduction or this
- - * software, it is not sold, rented, traded or otherwise marketed, and
- - * this copyright notice is included prominently in any copy
- - * made.
- - *
- - * The author make no claims as to the fitness or correctness of
- - * this software for any use whatsoever, and it is provided as is.
- - * Any use of this software is at the user's own risk.
- - *
- - * recmail: read a mail message on stdin, grab all addresses in To and Cc
- - * lines, and pass the full message to all addressees. This is useful to
- - * send the output of a recently edited mail message (with headers edited too).
- - * It is similar to sendmail -t, but only assumes /bin/mail.
- - * To use your own mailer, e. g. nmail, compile with -DMAILER=my_mailer.
- - */
- -
- -#ifdef SCCSID
- -static char *SccsId = "@(#)recmail.c 1.15 10/23/86";
- -#endif /* SCCSID */
- -
- -#include "params.h"
- -
- -#ifndef MAILER
- -#define MAILER "/bin/mail"
- -#endif
- -char mailer[] = MAILER;
- -
- -#define MAXRECIPS 100
- -char *recips[MAXRECIPS];
- -int nrecips = 0;
- -
- -main()
- -{
- - FILE *fd;
- - char *tmpf;
- - FILE *errfd;
- - char *errf;
- - char linebuf[1024];
- - int i, pid, wpid;
- - int exstat;
- - char *mypath;
- - int goodcnt, badcnt;
- - char *mktemp(), *getenv();
- -
- - tmpf = mktemp("/tmp/rmXXXXXX");
- - (void) close(creat(tmpf,0666));
- - fd = fopen(tmpf, "w");
- - errf = mktemp("/tmp/rmXXXXXX");
- - (void) close(creat(errf,0666));
- - errfd = fopen(errf, "w");
- - fprintf(errfd, "Subject: Returned mail\n");
- - fprintf(errfd, "\n ----- Transcript of session follows -----\n");
- - (void) fflush(errfd);
- - goodcnt = badcnt = 0;
- -
- - while (fgets(linebuf, sizeof linebuf, stdin) != NULL) {
- - if ((strncmp(linebuf, "Bcc: ", 5) == 0 ||
- - strncmp(linebuf, "bcc: ", 5) == 0 ||
- - strncmp(linebuf, "BCC: ", 5) == 0)) {
- - if (linebuf[5] != '\n')
- - addrecips(linebuf+5);
- - }
- - else if (fputs(linebuf, fd) == EOF)
- - goto werror;
- - if (linebuf[0] == '\n')
- - break;
- - if ((strncmp(linebuf, "To: ", 4) == 0 ||
- - strncmp(linebuf, "to: ", 4) == 0 ||
- - strncmp(linebuf, "TO: ", 4) == 0 ||
- - strncmp(linebuf, "Cc: ", 4) == 0 ||
- - strncmp(linebuf, "cc: ", 4) == 0 ||
- - strncmp(linebuf, "CC: ", 4) == 0) &&
- - linebuf[4] != '\n')
- - addrecips(linebuf+4);
- - }
- - if (!feof(stdin)) {
- - while (fgets(linebuf, sizeof linebuf, stdin) != NULL) {
- - if (fputs(linebuf, fd) == EOF) {
- -werror:
- - printf("write error on temp file\n");
- - exit(2);
- - }
- - }
- - }
- - /*
- - * Append the contents of the .signature file (if it exists) to
- - * the end of the mail message
- - */
- - {
- - char sigbuf[BUFSIZ];
- - register c;
- - register char *p = getenv("HOME");
- - FILE *infp;
- -
- - if (p) {
- - (void) sprintf(sigbuf, "%s/%s", p, ".signature");
- - if (infp = fopen(sigbuf, "r")) {
- - fprintf(fd,"---\n");
- - while ((c = getc(infp)) != EOF)
- - putc(c,fd);
- - (void) fclose(infp);
- - }
- - }
- - }
- - (void) fclose(fd);
- -
- - /*
- - * Force the path to only consider /bin and /usr/bin, since
- - * that's the version of mail we want (not /usr/ucb/mail)
- - */
- - if (mailer[0] != '/') {
- - register int e;
- - extern char **environ;
- - for (e = 0; environ[e] != NULL; ++e)
- - if (strncmp(environ[e], "PATH=", 5) == 0) {
- - environ[e] = "PATH=/bin:/usr/bin";
- - break;
- - }
- - }
- - mypath = getenv("PATH");
- - if (mypath)
- - strcpy(mypath, "/bin:/usr/bin");
- -
- - /*
- - * We send the copies out separately, because of a bug in
- - * USG's /bin/mail which will generate ANOTHER To: line,
- - * even though we already have one, if there are at least
- - * two recipients.
- - */
- - for (i=0; i<nrecips; i++) {
- - /*
- - * mail recips[i] < tmpf
- - */
- - pid = mailto(tmpf, errfd, recips[i]);
- - exstat = -1;
- - while ((wpid = wait(&exstat)) >= 0 && wpid != pid)
- - ;
- - if (exstat == 0)
- - goodcnt++;
- - else
- - badcnt++;
- - }
- - if (badcnt) {
- - mailback(errfd, tmpf, errf);
- - (void) unlink(tmpf);
- - (void) unlink(errf);
- - exit(1);
- - } else if (goodcnt == 0) {
- - fprintf(errfd, "recmail: no 'To:' line\n");
- - mailback(errfd, tmpf, errf);
- - (void) unlink(tmpf);
- - (void) unlink(errf);
- - exit (1);
- - }
- - (void) unlink(tmpf);
- - (void) unlink(errf);
- - exit (0);
- -}
- -
- -#define isok(c) (isprint(c) && (c) != ' ' && c != ',')
- -addrecips(line)
- -char *line;
- -{
- - char *front, *back, *tail;
- - char *malloc();
- -
- - tail = line + strlen(line);
- - for (front=line; front < tail; ) {
- - while (!isok(*front) && front < tail)
- - front++;
- - if (front >= tail)
- - break; /* skip end of line garbage */
- - for (back=front; isok(*back); back++)
- - ;
- - *back=0;
- - if (nrecips >= MAXRECIPS) {
- - printf("Too many destinations\n");
- - exit(2);
- - }
- - if ((recips[nrecips] = malloc(strlen(front) + 1)) == NULL) {
- - printf("Out of space\n");
- - exit(2);
- - }
- - (void) strcpy(recips[nrecips], front);
- - nrecips++;
- - front = back+1;
- - }
- -}
- -
- -int
- -mailto(tmpf, errfd, recip)
- -char *tmpf;
- -FILE *errfd;
- -char *recip;
- -{
- - register int pid;
- -
- - /*
- - * mail recips < tmpf
- - */
- - while ((pid = vfork()) == -1) {
- - fprintf(stderr, "fork failed, waiting...\r\n");
- - sleep(60);
- - }
- - if (pid == 0) {
- - (void) close(0);
- - (void) open(tmpf, 0);
- - if (errfd != NULL) {
- - (void) close(1);
- - (void) dup(fileno(errfd));
- - (void) fclose(errfd);
- - (void) close(2);
- - (void) dup(1);
- - }
- - execlp(mailer, mailer, recip, (char *)0);
- - perror(mailer);
- - exit(1);
- - }
- - return pid;
- -}
- -
- -mailback(errfd, tmpf, errf)
- -register FILE *errfd;
- -char *tmpf;
- -char *errf;
- -{
- - register FILE *fd;
- - register int c;
- - int exstat;
- - register int pid, wpid;
- - char *logn;
- - char *getlogin(), *getenv();
- - register struct passwd *pwd;
- -
- - if ((fd = fopen(tmpf, "r")) != NULL) {
- - fprintf(errfd, "\n ----- Unsent message follows -----\n");
- - while ((c = getc(fd)) != EOF)
- - putc(c, errfd);
- - (void) fclose(fd);
- - }
- - (void) fclose(errfd);
- - if ((logn = getlogin()) == NULL && (logn = getenv("USER")) == NULL) {
- - if ((pwd = getpwent(getuid())) == NULL)
- - return;
- - logn = pwd->pw_name;
- - }
- - pid = mailto(errf, (FILE *)NULL, logn);
- - while ((wpid = wait(&exstat)) >= 0 && wpid != pid)
- - ;
- -}
- *-*-END-of-src/recmail.c-*-*
- echo x - src/ftime.c 1>&2
- sed 's/.//' >src/ftime.c <<'*-*-END-of-src/ftime.c-*-*'
- -#ifdef SCCSID
- -static char *SccsId = "@(#)ftime.c 2.5 4/26/85";
- -#endif /* SCSCID */
- -
- -#include <sys/types.h>
- -struct timeb
- -{
- - time_t time;
- - unsigned short millitm;
- - short timezone;
- - short dstflag;
- -};
- -
- -extern long timezone;
- -extern int daylight;
- -
- -ftime(tp)
- -struct timeb *tp;
- -{
- - long t;
- -
- - time(&t);
- - tp->time = t;
- - tp->millitm = 0;
- - tp->timezone = timezone/60;
- - tp->dstflag = daylight;
- -}
- *-*-END-of-src/ftime.c-*-*
- exit
-
-